﻿#region zh-CHS 2006 - 2007 DemoSoft 团队 | en 2006 - 2007 DemoSoft Team

//     NOTES
// ---------------
//
// This file is a part of the MMOSE(Massively Multiplayer Online Server Engine) for .NET.
//
//                              2006-2007 DemoSoft Team
//
//
// First Version : by H.Q.Cai - mailto:caihuanqing@hotmail.com

/***************************************************************************
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU Lesser General Public License as published
 *   by the Free Software Foundation; either version 2.1 of the License, or
 *   (at your option) any later version.
 *
 ***************************************************************************/

#region zh-CHS 包含名字空间 | en Include namespace
using System;
using System.Linq;
using System.Text;
using System.Threading;
using System.Collections.Generic;
using Demo.Mmose.Core.Util;
using Demo.Mmose.Collections;
#endregion

namespace Demo.Mmose.Core.Common.Collections
{
    /// <summary>
    /// 
    /// </summary>
    public class SafeMultiDictionary<KeyT, ValueT>
    {
        #region zh-CHS 构造和初始化和清理 | en Constructors and Initializers and Dispose
        /// <summary>
        /// allowDuplicateValues == false
        /// </summary>
        public SafeMultiDictionary()
        {
        }

        /// <summary>
        /// 
        /// </summary>
        public SafeMultiDictionary( bool allowDuplicateValues )
        {
            m_MultiDictionary = new MultiDictionary<KeyT, ValueT>( allowDuplicateValues );
        }
        #endregion

        #region zh-CHS 共有属性 | en Public Properties
        /// <summary>
        /// 
        /// </summary>
        public int Count
        {
            get { return m_MultiDictionary.Count; }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public ValueT[] this[KeyT key]
        {
            get
            {
                ValueT[] valueArray = null;

                ReaderWriterLockSlimEx.EnterReadLock( m_LockMultiDictionary );
                {
                    ICollection<ValueT> valueCollection = m_MultiDictionary[key];
                    if ( valueCollection != null )
                    {
                        valueArray = new ValueT[valueCollection.Count];

                        int iIndex2 = 0;
                        foreach ( ValueT value in valueCollection )
                        {
                            valueArray[iIndex2] = value;

                            ++iIndex2;
                        }
                    }
                }
                ReaderWriterLockSlimEx.ExitReadLock( m_LockMultiDictionary );

                return valueArray;
            }
            set
            {
                ReaderWriterLockSlimEx.EnterWriteLock( m_LockMultiDictionary );
                {
                    m_MultiDictionary.Remove( key );

                    foreach ( ValueT valueItem in value )
                        m_MultiDictionary.Add( key, valueItem );

                    m_bIsValueChange = true;
                }
                ReaderWriterLockSlimEx.ExitWriteLock( m_LockMultiDictionary );
            }
        }

        #endregion

        #region zh-CHS 共有方法 | en Public Methods
        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 
        /// </summary>
        private MultiDictionary<KeyT, ValueT> m_MultiDictionary = new MultiDictionary<KeyT, ValueT>( false );
        /// <summary>
        /// 
        /// </summary>
        private ReaderWriterLockSlim m_LockMultiDictionary = new ReaderWriterLockSlim();
        #endregion
        /// <summary>
        /// 
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        public void Add( KeyT key, ValueT value )
        {
            ReaderWriterLockSlimEx.EnterWriteLock( m_LockMultiDictionary );
            {
                m_MultiDictionary.Add( key, value );

                m_bIsValueChange = true;
            }
            ReaderWriterLockSlimEx.ExitWriteLock( m_LockMultiDictionary );
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public bool Remove( KeyT key )
        {
            bool bReturn = false;

            ReaderWriterLockSlimEx.EnterWriteLock( m_LockMultiDictionary );
            {
                bReturn = m_MultiDictionary.Remove( key );

                m_bIsValueChange = true;
            }
            ReaderWriterLockSlimEx.ExitWriteLock( m_LockMultiDictionary );

            return bReturn;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public bool Remove( KeyT key, ValueT value )
        {
            bool bReturn = false;

            ReaderWriterLockSlimEx.EnterWriteLock( m_LockMultiDictionary );
            {
                bReturn = m_MultiDictionary.Remove( key, value );

                m_bIsValueChange = true;
            }
            ReaderWriterLockSlimEx.ExitWriteLock( m_LockMultiDictionary );

            return bReturn;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public bool ContainsKey( KeyT key )
        {
            bool bReturn = false;

            ReaderWriterLockSlimEx.EnterReadLock( m_LockMultiDictionary );
            {
                bReturn = m_MultiDictionary.ContainsKey( key );
            }
            ReaderWriterLockSlimEx.ExitReadLock( m_LockMultiDictionary );

            return bReturn;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public bool Contains( KeyT key, ValueT value )
        {
            bool bReturn = false;

            ReaderWriterLockSlimEx.EnterReadLock( m_LockMultiDictionary );
            {
                bReturn = m_MultiDictionary.Contains( key, value );
            }
            ReaderWriterLockSlimEx.ExitReadLock( m_LockMultiDictionary );

            return bReturn;
        }


        /// <summary>
        /// 
        /// </summary>
        void Clear()
        {
            ReaderWriterLockSlimEx.EnterWriteLock( m_LockMultiDictionary );
            {
                m_MultiDictionary.Clear();

                m_bIsValueChange = true;
            }
            ReaderWriterLockSlimEx.ExitWriteLock( m_LockMultiDictionary );
        }

        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 
        /// </summary>
        private KeyT[] m_KeyArray = new KeyT[0];
        /// <summary>
        /// 
        /// </summary>
        private KeyValuePair<KeyT, ValueT[]>[] m_KeyValuePairArray = new KeyValuePair<KeyT, ValueT[]>[0];
        /// <summary>
        /// 
        /// </summary>
        private bool m_bIsValueChange = true;
        #endregion

        #region zh-CHS 私有方法 | en Private Methods
        /// <summary>
        /// 
        /// </summary>
        private void InternalToArray()
        {
            ReaderWriterLockSlimEx.EnterReadLock( m_LockMultiDictionary );
            {
                if ( m_bIsValueChange == true )
                {
                    m_KeyArray = new KeyT[m_MultiDictionary.Count];

                    m_KeyValuePairArray = new KeyValuePair<KeyT, ValueT[]>[m_MultiDictionary.Count];

                    int iIndex = 0;
                    foreach ( KeyValuePair<KeyT,  ICollection<ValueT>> keyValuePair in m_MultiDictionary )
                    {
                        m_KeyArray[iIndex] = keyValuePair.Key;

                        ValueT[] valueArray = new ValueT[keyValuePair.Value.Count];

                        int iIndex2 = 0;
                        foreach ( ValueT value in keyValuePair.Value )
                        {
                            valueArray[iIndex2] = value;

                            ++iIndex2;
                        }

                        m_KeyValuePairArray[iIndex] = new KeyValuePair<KeyT, ValueT[]>( keyValuePair.Key, valueArray );

                        ++iIndex;
                    }

                    m_bIsValueChange = false;
                }
            }
            ReaderWriterLockSlimEx.ExitReadLock( m_LockMultiDictionary );
        }
        #endregion
        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        [MultiThreadedWarning( "zh-CHS", "当前的数组是列表临时产生的,不能保存数组用于以后操作:警告!" )]
        public KeyValuePair<KeyT, ValueT[]>[] ToArray()
        {
            InternalToArray();

            return m_KeyValuePairArray;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        [MultiThreadedWarning( "zh-CHS", "当前的数组是列表临时产生的,不能保存数组用于以后操作:警告!" )]
        public ValueT[] ToArrayValuesByKey( KeyT key )
        {
            return this[key];
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        [MultiThreadedWarning( "zh-CHS", "当前的数组是列表临时产生的,不能保存数组用于以后操作:警告!" )]
        public KeyT[] ToArrayKeys()
        {
            InternalToArray();

            return m_KeyArray;
        }
        #endregion
    }
}
#endregion
